package com.g2room.driving.grap.life;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.alibaba.fastjson.JSON;
import com.g2room.driving.grap.GenericGrap;
import com.g2room.driving.grap.life.model.po.ComShopComment;
import com.g2room.myuall.grap.ky.model.po.GrapErr;
import com.g2room.myuall.util.DbUtil;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
/**
 * 大众点评评价信息
 * @author butterfly
 *
 */
public class GrabDzdpCommentDataByProxy implements Runnable {
	public static String baseUrl = "http://www.dianping.com/shop/#id#/review_more";
	private String source = "大众点评";
	@Override
	public void run() {
//		for(Integer id : subMap.keySet()) {
//			getPage(id, subMap.get(id));
//		}
	}
	static int lastId = 440;
	static String lastListUrl = null;
	static boolean urlFlag = false;
	static long lastErrTime = 0l;
	public static void main(String[] args) {
		GrabDzdpCommentDataByProxy gdc = new  GrabDzdpCommentDataByProxy();
		gdc.getdata();
		
//		Map<Integer, Integer> ids= getShopIds();
//		int total = 1326;
//		Map<Integer, Integer> subMap1 = new HashMap<Integer, Integer>();
//		int i = 0;
//		for(int id: ids.keySet()) {
//			i++;
//			subMap1.put(id, ids.get(id));
//			if(i % total == 0) {
//				GrabDzdpCommentDataByProxy gdc = new  GrabDzdpCommentDataByProxy();
//				gdc.subMap.putAll(subMap1);
//				Thread t = new Thread(gdc);
//				t.start();
//				subMap1.clear();
//			}
//		}
//		// 
//		if(subMap1.size() > 0) {
//			GrabDzdpCommentDataByProxy gdc = new  GrabDzdpCommentDataByProxy();
//			gdc.subMap.putAll(subMap1);
//			Thread t = new Thread(gdc);
//			t.start();
//		}
    }
	
	public void getdata() {
		Map<Integer, Integer> ids= getShopIds();
		boolean flag = false;
		for(int id: ids.keySet()) {
			if(id == lastId) {
				flag = true;
//				continue;
			}
//			if(id == 298) break;
			try {
				if(flag) {
					int min = getmin(3, 15);
					System.out.print(ids.get(id) + "==" + id + " , sleep=" + min);
					Thread.sleep(min);
					getPage(id, ids.get(id));
					lastId = id;
				}
			} catch (Exception e) {
				long l = new Date().getTime();
				if(l - lastErrTime < 30000) break;
				lastErrTime = l;
				System.out.println(ids.get(id) + "==id=" +e.getMessage());
				try {
					Thread.sleep(400000);
					getdata();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * 获取头部导航菜单
	 * @param url
	 * @throws Exception 
	 * @throws FailingHttpStatusCodeException
	 * @throws MalformedURLException
	 * @throws IOException
	 */
	public void getPage(int id, int oid) throws Exception {
		String url = baseUrl.replace("#id#", oid+"");
		Document doc = null;
		try {
			doc = GenericGrap.getDocumentByIp(url);
		} catch (Exception e) {
			GrapErr ge = new  GrapErr();
			ge.setUrl(url);
			ge.setType("1");
			ge.setDescription("获取URL错误："+e.getMessage());
			insert2ErrDb(ge);
			if(e.getMessage().contains("HTTP error fetching URL")) throw e;
			return;
		}
		if(null == doc) return;
		List<String> pageUrls = new ArrayList<String>();
		pageUrls.add(url);
		// 获取分页 http://www.dianping.com/shop/2722525/review_more?pageno=35
		// 没有评论
		Elements pageels = doc.getElementsByAttributeValue("class", "Pages");
		if(null == pageels || pageels.isEmpty()) {
			System.out.print("=没有评论\n");
			return;
		}
		
		try {
			Elements aels = doc.getElementsByAttributeValue("class", "PageLink");
			if(null != aels && !aels.isEmpty()) {
				int pn = Integer.valueOf(aels.get(aels.size() - 1).text());
				for(int i = 2; i< pn+1; i++) {
					pageUrls.add(url + "?pageno=" + i);
				}
			}

			System.out.print("=评论列表页：" + pageUrls.size() + "页");
			for(String pageUrl : pageUrls) {
				if(!urlFlag && (null == lastListUrl || pageUrl.equals(lastListUrl))) {
					urlFlag = true;
					System.out.print("\n");
					if(null != lastListUrl) continue;
				}
				if(urlFlag) {
					int i = getmin(3, 20);
					System.out.print("=" + i + "毫秒\n");
					Thread.sleep(i);
					getList(pageUrl, id);
					lastListUrl = pageUrl;
				}
			}
		} catch(Exception e) {
			GrapErr ge = new  GrapErr();
			ge.setUrl(url);
			ge.setType("2");
			ge.setContent(id+"");
			ge.setDescription("获取page 错误："+e.getMessage());
			insert2ErrDb(ge);
			if(e.getMessage().contains("HTTP error fetching URL")) throw e;
		}
	}
	
	private int getmin(int min, int max) {
		Random r = new Random();
		// 随机3~5秒访问看看
		int i = r.nextInt(max);
		if(i >= min && i<=max) {
			return i * 1000;
		} else {
			return getmin(min, max);
		}
	}

	public void getList(String url, int id) throws Exception {
		Document doc = null;
		try {
			doc = GenericGrap.getDocumentByIp(url);
		} catch(Exception e) {
			GrapErr ge = new  GrapErr();
			ge.setUrl(url);
			ge.setType("3");
			ge.setContent(id+"");
			ge.setDescription("获取List 错误："+e.getMessage());
			insert2ErrDb(ge);
			if(e.getMessage().contains("HTTP error fetching URL")) throw e;
			return;
		}
		List<ComShopComment> cscs = new ArrayList<ComShopComment>();
		Elements els = doc.getElementsByAttributeValue("class", "comment-list");
		if(null != els && !els.isEmpty()) {
			els = els.first().getElementsByTag("ul");
			if(null != els && !els.isEmpty()) {
				for(Element liel : els.first().children()) {
					if(!liel.tagName().equals("li")) continue;
					
					ComShopComment csc = new ComShopComment();
					try {
						csc.setSource(source);
						csc.setSourceUrl(url);
						csc.setShopId(id);
						// 获取头像
						Elements liels = liel.getElementsByAttributeValue("class", "pic");
						if(null != liels && !liels.isEmpty()) {
							liels = liels.first().getElementsByTag("img");
							if(null != liels && !liels.isEmpty()) {
								csc.setHead(liels.first().attr("src"));
								csc.setUsername(liels.first().attr("alt"));
							}
						}
						
						// 获取内容
						liels = liel.getElementsByAttributeValue("class", "user-info");
						if(null != liels && !liels.isEmpty()) {
							for(Element el : liels.first().children()) {
								String clazz = el.attr("class");
								if(clazz.contains("item-rank-rst")) {
									csc.setStar(el.attr("class").replace("item-rank-rst irr-star", ""));
								} else if(clazz.contains("comm-per")) {
									csc.setSpendPerhead(el.text().replace("人均 ￥",""));
								} else if(clazz.contains("comment-rst")) {
									Elements pjels = el.getElementsByTag("span");
									if(null != pjels && pjels.size() == 3) {
										pjels.get(0).getElementsByTag("em").remove();
										csc.setFlavor(pjels.get(0).text());
										pjels.get(1).getElementsByTag("em").remove();
										csc.setEnvironment(pjels.get(1).text());
										pjels.get(2).getElementsByTag("em").remove();
										csc.setServer(pjels.get(2).text());
									}
								}
							}
						}
						
						// 获取内容
						liels = liel.getElementsByAttributeValue("class", "J_brief-cont");
						if(null != liels && !liels.isEmpty()) {
							csc.setContent(liels.first().html());
						}
						
						// 获取评价图片
						liels = liel.getElementsByAttributeValue("class", "shop-photo");
						if(null != liels && !liels.isEmpty()) {
							liels = liels.first().getElementsByTag("img");
							String imgs = "";
							for(Element el : liels) {
								if(imgs.length() > 0) imgs += ";";
								imgs += el.attr("panel-src");
							}
							csc.setImages(imgs);
						}
						
						// 获取评价时间
						liels = liel.getElementsByAttributeValue("class", "misc-info");
						if(null != liels && !liels.isEmpty()) {
							liels = liels.first().getElementsByAttributeValue("class", "time");
							if(null != liels && !liels.isEmpty()) {
								csc.setCommentTime(liels.first().text());
							}
						}
						
						cscs.add(csc);
					} catch (Exception e) {
						GrapErr ge = new  GrapErr();
						ge.setUrl(url);
						ge.setType("4");
						ge.setContent(JSON.toJSONString(csc));
						ge.setDescription("获取List 内容错误："+e.getMessage());
						insert2ErrDb(ge);
					}
				}
			}
		}
		insert2CscDb(cscs);
	}

	
	public void insert2CscDb(List<ComShopComment> cscs) {
		String sql = "insert into com_shop_comment(username,images,spend_perhead,shop_name,star,environment,content,head,server,comment_time,flavor,shop_id) values(?,?,?,?,?,?,?,?,?,?,?,?)";
		PreparedStatement ps = null;
		try {
			ps = DbUtil.getComConn().prepareStatement(sql);
			for(ComShopComment cc : cscs) {
				ps.setString(1, getUtf8Str(cc.getUsername()));
				ps.setString(2, cc.getImages());
				ps.setString(3, cc.getSpendPerhead());
				ps.setString(4, cc.getShopName());
				ps.setString(5, cc.getStar());
				ps.setString(6, getUtf8Str(cc.getEnvironment()));
				ps.setString(7, getUtf8Str(cc.getContent()));
				ps.setString(8, cc.getHead());
				ps.setString(9, getUtf8Str(cc.getServer()));
				ps.setString(10, cc.getCommentTime());
				ps.setString(11, getUtf8Str(cc.getFlavor()));
				ps.setInt(12, cc.getShopId());
				ps.addBatch();
			}	
			ps.executeBatch();	
		} catch (Exception e) {
			e.printStackTrace();
			GrapErr ge = new  GrapErr();
			ge.setType("5");
			ge.setContent(JSON.toJSONString(cscs));
			ge.setDescription("插入Detail错误："+e.getMessage());
			insert2ErrDb(ge);
			return;
		} finally {
			if(null != ps) {
				try {
					ps.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private String getUtf8Str(String str) {
		try {
			str = null == str ? null : new String(str.getBytes(), "utf-8").replaceAll("[\\ud83c\\udc00-\\ud83c\\udfff]|[\\ud83d\\udc00-\\ud83d\\udfff]|[\\u2600-\\u27ff]", "");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return str;
	}

	public void insert2ErrDb(GrapErr ge) {
		PreparedStatement grapPs = null;
		try {
			grapPs = DbUtil.getComConn().prepareStatement("insert into grap_err(description,url,content,type) values(?,?,?,?)");
			grapPs.setString(1, ge.getDescription());
			grapPs.setString(2, ge.getUrl());
			grapPs.setString(3, ge.getContent());
			grapPs.setString(4, ge.getType());
			grapPs.execute();
			grapPs.close();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(null != grapPs) {
				try {
					grapPs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static List<GrapErr> getErrs() {
		List<GrapErr> univs = new ArrayList<GrapErr>();
		try {
			Connection connection = DbUtil.getComConn();
			Statement statement = connection.createStatement();
			String sql = "select * from grap_err";
			ResultSet rs = statement.executeQuery(sql);
			while(rs.next()) {
				GrapErr univ = new GrapErr();
				univ.setId(rs.getInt("id"));
				univ.setUrl(rs.getString("url"));
				univ.setType(rs.getString("type"));
				univ.setContent(rs.getString("content"));
				univs.add(univ);
			}
			rs.close();
			statement.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
		return univs;
	}
	
	public static void delErr(int id) {
		PreparedStatement grapPs = null;
		try {
			grapPs = DbUtil.getComConn().prepareStatement("delete from grap_err where id=?");
			grapPs.setInt(1, id);
			grapPs.execute();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(null != grapPs) {
				try {
					grapPs.close();
				} catch (SQLException e) {
					
				}
			}
		}
	}
	
	public static void delMenu(int id) {
		PreparedStatement grapPs = null;
		try {
			grapPs = DbUtil.getComConn().prepareStatement("delete from com_menu where shop_id=?");
			grapPs.setInt(1, id);
			grapPs.execute();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if(null != grapPs) {
				try {
					grapPs.close();
				} catch (SQLException e) {
					
				}
			}
		}
	}

	public static Map<Integer, Integer> getShopIds() {
		Map<Integer, Integer> map =new HashMap<Integer, Integer>();
		try {
			Connection connection = DbUtil.getComConn();
			Statement statement = connection.createStatement();
			String sql = "select  id,old_id from com_shop order by id asc";
			ResultSet rs = statement.executeQuery(sql);
			while(rs.next()) {
				map.put(rs.getInt("id") ,rs.getInt("old_id"));
			}
			rs.close();
			statement.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
		return map;
	}
}
